package org.idontknow.blocks;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

class Problem {

	public static Logger log = Logger.getLogger(Problem.class.getName());

	private static Block[] block;

	Problem(int size) {

		// System.out.println(Command.blockStack);
		// Command.blockStack = new Stack[size];
		// System.out.println(Command.blockStack);
		// for (int i = 0; i < size; i++) {
		// Command.blockStack[i] = new Stack(size);
		// Command.blockStack[i].put(new Block(i, i, 0));
		// }

		// block = new Block[size];

		block = Command.init(size);
		// for (int i = 0; i < size; i++) {
		// block[i] = new Block(i, i, 0);
		// }
	}

	public static void main(String[] args) {

		PropertyConfigurator.configure("log4j.properties");
		// BasicConfigurator.configure();
		// log.error("Let's start logging!");
		int n;
		try {
			FileReader fdr = new FileReader(System.getProperty("user.dir")
					+ File.separator + "src" + File.separator + "org"
					+ File.separator + "idontknow" + File.separator + "blocks"
					+ File.separator + "inputBlocks");
			BufferedReader bdr = new BufferedReader(fdr);
			String line = null;
			String[] s = new String[4];
			Command command = null;

			line = bdr.readLine();
			n = Integer.parseInt(line);
			// int idx = 0;

			new Problem(n);

			while (!(line = bdr.readLine()).equals("quit")) {

				// System.out.println(line);
				// System.out.println(idx);

				int from, to;

				StringTokenizer st = new StringTokenizer(line);
				for (int i = 0; i < 4; i++) {
					if (!st.hasMoreTokens())
						throw new BadInputFormatException();
					s[i] = st.nextToken();
				}

				from = Integer.parseInt(s[1]);
				to = Integer.parseInt(s[3]);

				if (s[0].charAt(0) == '#') {
					log.debug("Got a commented line, bypassing...");
					continue;
				}

				if (s[0].equals("move")) {
					if (s[2].equals("onto")) {
						command = new MoveOnto(block[from], block[to]);
					} else {
						command = new MoveOver(block[from], block[to]);
					}
				} else {
					if (s[2].equals("onto")) {
						command = new PileOnto(block[from], block[to]);
					} else {
						command = new PileOver(block[from], block[to]);
					}
				}

				if ((from == to)
						|| (block[from].getStackId() == block[to].getStackId())) {
					log
							.info("This is a logically invalid command, its gonna be ignored!");
					// log.info("-------- Command: " + line + " --------\n");
					// log.info("This seems to be an illegal command, il do
					// nothing!\n");
					System.out.println("-------- Command: " + line
							+ " --------\n");
					System.out
							.println("This seems to be an illegal command, il do nothing!\n");
					log
							.info("An invalid command ignored.\n\n----------------------------------------");

				} else {
					log.debug("Executing a valid command: " + line);
					command.execute();
				}
			}
			log.debug("All commands finished, quitting application...");

			// System.out.println(idx);
		} catch (FileNotFoundException e) {
			log.fatal("Error opening input file!");
			e.printStackTrace();
		} catch (IOException e) {
			log.fatal("Error reading input file!");
			e.printStackTrace();
		} catch (BadInputFormatException e) {
			log.fatal("Bad command line in input file!");
			e.printStackTrace();
		}

		// int n = 10;
		//		
		// Block[] block = new Block[n];
		//
		// for (int i = 0; i < n; i++)
		// block[i] = Command.blockStack[i].getBlock(0);
		//
		// (new MoveOnto(block[9], block[1])).execute();
		// (new MoveOver(block[8], block[9])).execute();
		// (new MoveOver(block[7], block[1])).execute();
		// (new MoveOver(block[6], block[1])).execute();
		// (new PileOver(block[8], block[6])).execute();
		// (new PileOver(block[8], block[5])).execute();
		// (new MoveOver(block[2], block[1])).execute();
		// (new MoveOver(block[4], block[9])).execute();

		// (new PileOver(block[2], block[6])).execute();
		// Command.printStacks();
		// (new PileOver(block[6], block[8])).execute();
		// Command.printStacks();
		// (new PileOver(block[2], block[0])).execute();
		// Command.printStacks();
	}
}
